package com.crm.aspect;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import org.apache.commons.lang3.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;

import static java.util.stream.Collectors.joining;

/**
 * @author zjd
 * @Title:
 * @Description:
 * @date 2021/6/216:46
 */
@Aspect
@Component
@Slf4j
public class WebLogAspect {


    // 配置切入点
    //@Pointcut("@annotation(com.crm.annotation.WebLog)")
    @Pointcut("execution(* com.crm.controller*..*(..))")
    public void webLog() {
        // 该方法无方法体,主要为了让同类中其他方法使用此切入点
    }

    //指定切点前的处理方法
    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) throws Exception {
        //获取request对象
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        StringBuilder sb = new StringBuilder();
        //拼接请求内容
        sb.append("\n请求路径:" + request.getRequestURL().toString() + "  " + request.getMethod() + "\n");
        //判断请求是什么请求
        if (request.getMethod().equalsIgnoreCase(RequestMethod.GET.name())) {
            Map<String, String[]> parameterMap = request.getParameterMap();
            Map<String, String> paramMap = new HashMap<>();
            parameterMap.forEach((key, value) -> paramMap.put(key, Arrays.stream(value).collect(joining(","))));
            sb.append("请求内容:" + JSON.toJSONString(paramMap));
        } else if (request.getMethod().equalsIgnoreCase(RequestMethod.POST.name())) {
            Object[] args = joinPoint.getArgs();
            StringBuilder stringBuilder = new StringBuilder();
            Arrays.stream(args).forEach(object -> stringBuilder.append(object.toString().replace("=",":")));
            if (stringBuilder.length() == 0){
                stringBuilder.append("{}");
            }
            sb.append("请求内容:" + stringBuilder.toString());
        }
        log.info(sb.toString());
    }

    //指定切点前的处理方法
    @AfterReturning(pointcut = "webLog()",returning = "result")
    public void doAfterReturning(Object result) {
        if (ObjectUtils.isEmpty(result)){
            return;
        }
        log.info("\n返回結果:" + JSON.toJSONString(result));
    }

   /* @Resource
    private HttpServletRequest request;

    @Pointcut("execution(* com.crm.controller*..*(..))")
    public void webLog() {
        log.info(request.getParameterMap().toString());
    }

    @AfterReturning(pointcut = "webLog()", returning = "returnValue")
    public void afterReturning(JoinPoint joinPoint, Object returnValue) {

            devEnvironmentLog(joinPoint, returnValue);
        *//*} else {
            productEnvironmentLog(joinPoint, returnValue);
        }*//*
    }

    *//**
     * @Description: 开发环境console打印信息
     * @Param:
     *//*
    private void devEnvironmentLog(JoinPoint joinPoint, Object returnValue) {
        StringBuilder sb = new StringBuilder("\nSpringMVC action report -------- ")
                .append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()))
                .append(" ------------------------------\n");
        sb.append(getController(joinPoint));
        sb.append(getMethod(joinPoint));
        sb.append(getUri());
        sb.append(getParameter(joinPoint));
        sb.append("RemoteAddr  : " + getIpAddr(request) + "\n");
        sb.append(getReturn(returnValue));
        sb.append("--------------------------------------------------------------------------------\n");
        System.out.print(sb.toString());
    }

    *//**
     * @Description: 正式环境打印的信息
     * @Param:
     *//*
    private void productEnvironmentLog(JoinPoint joinPoint, Object returnValue) {
        StringBuilder sb = new StringBuilder();
        sb.append(request.getRequestURI()).append(", ");
        sb.append("IP: " + getIpAddr(request)).append(", [");
        Map<String, String[]> parameters = request.getParameterMap();
        for (Map.Entry<String, String[]> entity : parameters.entrySet()) {
            sb.append(String.format("%s = %s, ", entity.getKey(), StringUtils.join(entity.getValue(), ',')));
        }
        sb.delete(sb.length() - 2, sb.length()).append("]");
        log.info(sb.toString());
    }

    private Map<String, MultipartFile> getRequestFileMap(JoinPoint joinPoint) {
        Map<String, MultipartFile> fileMap = null;
            Object[] args = joinPoint.getArgs();
            for (Object object : args) {
                if (object instanceof MultipartHttpServletRequest) {
                    MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) object;
                    fileMap = multipartHttpServletRequest.getFileMap();
                    break;
                }
        }
        return fileMap;
    }

    private String getController(JoinPoint joinPoint) {
        return new StringBuffer().append("Controller  : ").append(joinPoint.getTarget().getClass().getName()).append(".(")
                .append(joinPoint.getTarget().getClass().getSimpleName()).append(".java:1)").toString();
    }

    private String getMethod(JoinPoint joinPoint) {
        return new StringBuffer().append("\nMethod      : ").append(joinPoint.getSignature().getName()).append("\n").toString();
    }

    private String getUri() {
        String uri = request.getRequestURI();
        if (uri != null) {
            return new StringBuffer().append("url         : ").append(uri)
                    .append(" user=" + request.getRemoteUser()).append("\n").toString();
        }
        return "";
    }

    private String getParameter(JoinPoint joinPoint) {
        StringBuffer sb = new StringBuffer();
        Map<String, MultipartFile> fileMap = getRequestFileMap(joinPoint);
        Enumeration<String> e = request.getParameterNames();
        if (e.hasMoreElements() || (fileMap != null && fileMap.size() > 0)) {
            sb.append("Parameter   : ");
            while (e.hasMoreElements()) {
                String name = e.nextElement();
                String[] values = request.getParameterValues(name);
                if (values.length == 1) {
                    sb.append(name).append("=").append(values[0]);
                } else {
                    sb.append(name).append("[]={");
                    for (int i = 0; i < values.length; i++) {
                        if (i > 0) {
                            sb.append(",");
                        }
                        sb.append(values[i]);
                    }
                    sb.append("}");
                }
                sb.append("  ");
            }
            if (fileMap != null && fileMap.size() > 0) {
                for (Map.Entry<String, MultipartFile> entry : fileMap.entrySet()) {
                    MultipartFile file = entry.getValue();
                    sb.append(entry.getKey()).append("=").append(file.getOriginalFilename());
                    sb.append(" (contentType=" + file.getContentType() + ",size=" + file.getSize() + ")");
                    sb.append("  ");
                }
            }
            sb.append("\n");
        }
        return sb.toString();
    }

    private String getReturn(Object returnValue) {
        StringBuffer sb = new StringBuffer();
        String returnJSON = "";
        returnJSON = JSONObject.toJSONString(returnValue);
        sb.append("return      : " + returnJSON);
        sb.append("\n");
        return sb.toString();
    }

    public static String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader( "x-forwarded-for" );
        if (ip == null || ip.length() == 0 || " unknown " .equalsIgnoreCase(ip)) {
            ip = request.getHeader( "Proxy-Client-IP" );
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader( "WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if (ip.equals("0:0:0:0:0:0:0:1")){
            ip = "127.0.0.1";
        }
        return ip;
    }
*/
}
